iT邦幫忙

2022 iThome 鐵人賽

DAY 30
0
自我挑戰組

30天深入淺出Redux系列 第 30

Redux 深入淺出 - [ Day 30 ] React RTK Query Typescript todo list - 新增功能 & 結語

  • 分享至 

  • xImage
  •  

今天是最後一篇了,我們接著完成我們最後的新增功能吧!

https://media.giphy.com/media/SwpfkMlXB3FoTbrrF4/giphy.gif

其實新增功能與先前的部分沒有差太多,一樣我們先回到 todoApi 去處理新增的功能,如下:

// src/features/api/todoApi.ts
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"

// 做一份與 server 相同的 Todo 格式提供 component 使用
export interface Todo {
  id: number;
  text: string;
  active: boolean;
  done: boolean;
}

// 這裡 createApi 會自動將 endpoints 的 name 去組成相對應的 query
// 以 getAll 為例,使用時會組成 useGetAllQuery 的 function
export const todoApi = createApi({
  reducerPath: 'todoApi',
  baseQuery: fetchBaseQuery({ baseUrl: 'http://localhost:8080/'}),
  tagTypes: ['Todos'],
  endpoints: (builder) => ({
    // 取全部資料
    getAll: builder.query<Todo[], void>({
      // 這裡的 query 代表接續 base 要傳入的值,providesTags 就是記錄一下對應的 tagType 詳細 https://redux-toolkit.js.org/rtk-query/usage/automated-refetchin 
      query: () => `todos`,
      providesTags: [{type: 'Todos', id: 'LIST'}]
    }),
    // 修改 todo
    // 這裡採用 mutation 意思是會拿取先前的 todo 然後回傳一個新的 todo 這段的概念與 React query 是相同的。
    updateTodo: builder.mutation<Todo, Todo>({
      // 這裡就是帶入參數的做法
      query(todo) {
        return {
          url: `todos/${todo.id}`,
          method: 'PUT',
          body: todo,
        };
      },
      // invalidatesTag 會自動去更新相對的 tagType 詳細一樣 https://redux-toolkit.js.org/rtk-query/usage/automated-refetchin
      invalidatesTags: [{type: 'Todos', id: 'LIST'}]
    }),
    // 刪除功能
    deleteTodo: builder.mutation<Todo, Todo>({
      query(todo) {
        return {
          url: `todos/${todo.id}`,
          method: 'DELETE',
          body: todo,
        };
      },
      invalidatesTags: [{type: 'Todos', id: 'LIST'}]
    }),
    // 新增功能
    addTodo: builder.mutation<string, string>({
      query(text) {
        return {
          url: `todos`,
          method: 'POST',
          body: {
            text,
          }
        };
      },
      invalidatesTags: [{type: 'Todos', id: 'LIST'}]
    })
  })
})

再來,我們接著調整畫面讓新增的段落顯示出來:

// src/components/TodosList.tsx
import { useCallback, useRef } from "react";
import { Todo, todoApi } from "../features/api/todoApi"

const TodosList = () => {
  // 使用剛才的 getAll query
  const { data } = todoApi.useGetAllQuery();
  // 這裡使用剛才的 updateTodo
  const [ updateTodo ] = todoApi.useUpdateTodoMutation();
  // 這裡使用剛才的 deleteTodo
  const [ deleteTodo ] = todoApi.useDeleteTodoMutation();
  // 這裡使用剛才的 addTodo
  const [ addTodo ] = todoApi.useAddTodoMutation();
  // 和之前一樣處理 input
  const addTextRef = useRef<HTMLInputElement>(null);
  // 這裡的話就是一般 react 的常規操作
  const onToggle = useCallback((todo: Todo) => {
    updateTodo({...todo, done: !todo.done})
  }, [updateTodo])
  // 與上述相同再操作一次
  const onDelete = useCallback((todo: Todo) => {
    deleteTodo(todo)
  }, [deleteTodo])
  const onAdd = useCallback(() => {
    addTodo(addTextRef.current!.value ?? '');
    addTextRef.current!.value = '';
  }, [addTodo])

  return (
    <div className="card" style={{margin: '1rem 0'}}>
      {data?.map((todo) => (
        <div className="f-b-c" key={todo.id}>
          <div>
            <input type="checkbox" checked={todo.done} onChange={() => onToggle(todo)}/>
            <span>{todo.text}</span>
          </div>
          <button onClick={() => onDelete(todo)}>delete</button>
        </div>
      ))}
      <div>
        <input type="text" ref={addTextRef} />
        <button onClick={onAdd}>add</button>
      </div>
    </div>
  )
}

export default TodosList

測試的時候不要忘記確認 server 是有在運行的喔!

結語

這次的內容我相信是很充足的了,從最基本的 redux → redux-toolkit → react-redux → with Typescript → RTK query ,基本上都是能直接應用在工作上的情境,也是我使用他的一些經驗總結,一直以來我也只在工作時會使用這樣的工具,當然很多新的工具也是有露出頭啦,但以實務經驗來說,它確實是首選,而且也存在好長一段時間了,可以兼容的版本也是好幾代的呢!

之後也會分享一些我所使用過有趣的狀態管理工具,但說真的,要能寫30篇的內容不參水分真的有點難,這次的紀錄我會放在我的 gitHub 上面供大家參閱,裏面的 5 個資料夾分別紀錄了這 30 天的技術精華,我有盡量站在初學者的角度去撰寫,但各位如果還是有疑問的可以再用關鍵字 google 或是留言告知,我盡快回覆,那麼今年的參賽歷程就到這邊了,感謝各位一路相挺,明年再見!!

source code: gitHub連結


上一篇
Redux 深入淺出 - [ Day 29 ] React RTK Query Typescript todo list (更新 & 刪除)
下一篇
[DLC] React Query 補充包
系列文
30天深入淺出Redux31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
DannyChen
iT邦研究生 4 級 ‧ 2022-10-11 13:24:20

redux真的水很深,感謝分享/images/emoticon/emoticon41.gif,也恭喜三十天挑戰成功~~/images/emoticon/emoticon42.gif

LucianoLee iT邦研究生 5 級 ‧ 2022-10-11 16:21:27 檢舉

謝謝,更多細節其實在我的 gitHub 連結會比較好看懂。

我要留言

立即登入留言